﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using ST.Common.Util.Logging;
using ST.Common.Util.Model;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace ST.Common.Util
{
	public class HttpHelper
	{
		//private static string USER_AGENT = string.Format("WXPaySDK/{3} ({0}) .net/{1} {2}", Environment.OSVersion, Environment.Version, WxPayConfig.GetConfig().GetMchID(), typeof(HttpHelper).Assembly.GetName().Version);

		public static ILogger logger = LoggingHelper.CreateLogger<HttpHelper>();

		public HttpHelper(ILogger<HttpHelper> _logger, IWebHostEnvironment env)
		{
			logger = _logger;
		}

		public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
		{
			//直接确认，否则打不开    
			return true;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="url"></param>
		/// <param name="paras"></param>
		/// <param name="timeout">超时（单位秒）</param>
		/// <param name="certFullPath">证书路径（全路径）</param>
		/// <param name="certPasswd">证书密码</param>
		/// <returns></returns>
		public static string Post(string url, string paras, int timeout, string certFullPath, string certPasswd, string contentType)
		{
			//GC.Collect();//垃圾回收，回收没有正常关闭的http连接

			if (logger.IsEnabled(LogLevel.Debug))
			{
				logger.LogDebug("POST请求参数->url：{0}，paras：{1}，timeout：{2}，certFullPath：{3}，certPasswd：{4}", url, paras, timeout, certFullPath, certPasswd);
			}
			string result = string.Empty;//返回结果
			HttpWebRequest req = null;
			HttpWebResponse resp = null;
			try
			{
				//设置最大连接数
				ServicePointManager.DefaultConnectionLimit = 200;
				////设置https验证方式
				//if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
				//{
				//	ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
				//}

				req = (HttpWebRequest)WebRequest.Create(url);

				req.Method = "POST";
				req.Timeout = timeout * 1000;
				req.ContentType = contentType;
				//设置代理服务器
				//WebProxy proxy = new WebProxy();                          //定义一个网关对象
				//proxy.Address = new Uri(WxPayConfig.PROXY_URL);              //网关服务器端口:端口
				//request.Proxy = proxy;

				//是否使用证书
				if (!string.IsNullOrEmpty(certFullPath))
				{
					//string certFullPath = Path.Combine(Directory.GetCurrentDirectory(), certPath);
					X509Certificate2 cert = new X509Certificate2(certFullPath, certPasswd);
					req.ClientCertificates.Add(cert);
				}

				if (!string.IsNullOrEmpty(paras))
				{
					byte[] bytesReq;
					if (paras.StartsWith("<"))//xml类型
					{
						req.ContentType = "text/xml";//设置POST的数据类型
						bytesReq = Encoding.UTF8.GetBytes(paras);
					}
					else if (paras.StartsWith("?") || paras.StartsWith("&"))
					{
						bytesReq = Encoding.UTF8.GetBytes(paras.Substring(1));
					}
					else
					{
						bytesReq = Encoding.UTF8.GetBytes(paras);
					}
					req.ContentLength = bytesReq.Length;//设置POST的数据长度

					using (Stream streamReq = req.GetRequestStream())//往服务器写入数据
					{
						streamReq.Write(bytesReq, 0, bytesReq.Length);
					}
				}

				//获取服务端返回
				resp = (HttpWebResponse)req.GetResponse();
				string respContentType = resp.ContentType;
				//获取服务端返回数据
				using (Stream respStream = resp.GetResponseStream())
				{
					using (StreamReader sr = new StreamReader(respStream, Encoding.UTF8))
					{
						result = sr.ReadToEnd().Trim();
					}
				}
				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("POST请求返回->{0}", result);
				}
			}
			catch (System.Threading.ThreadAbortException e)
			{
				logger.LogError("POST请求出错，ThreadAbortException，" + e);
				System.Threading.Thread.ResetAbort();
			}
			catch (WebException e)
			{
				if (e.Status == WebExceptionStatus.ProtocolError)
				{
					logger.LogError("POST请求出错，WebException，StatusCode：" + ((HttpWebResponse)e.Response).StatusCode + "，StatusDescription：" + ((HttpWebResponse)e.Response).StatusDescription + "，" + e);
				}
				else
				{
					logger.LogError("POST请求出错，WebException，" + e);
				}
			}
			catch (Exception e)
			{
				logger.LogError("POST请求出错，Exception，" + e);
			}
			finally
			{
				//关闭连接和流
				if (resp != null)
				{
					resp.Close();
				}
				if (req != null)
				{
					req.Abort();
				}
			}
			return result;
		}

		/// <summary>
		/// 普通的form提交
		/// </summary>
		/// <param name="url"></param>
		/// <param name="paras"></param>
		/// <param name="timeout">超时（单位秒）</param>
		/// <returns></returns>
		public static string Post(string url, string paras, int timeout = 30)
		{
			return Post(url, paras, timeout, null, null, "application/x-www-form-urlencoded");
		}

		/// <summary>
		/// json格式提交
		/// </summary>
		/// <param name="url"></param>
		/// <param name="paras"></param>
		/// <param name="timeout"></param>
		/// <returns></returns>
		public static string Post(string url, object paras, int timeout = 30)
		{
			return Post(url, Newtonsoft.Json.JsonConvert.SerializeObject(paras), timeout, null, null, "application/json; charset=utf-8");
		}

		/// <summary>
		/// json格式提交（并且根据响应类型自动处理）
		/// </summary>
		/// <param name="url"></param>
		/// <param name="paras"></param>
		/// <param name="timeout"></param>
		/// <returns></returns>
		public static HttpResult PostStream(string url, object paras, int timeout = 30)
		{
			//GC.Collect();//垃圾回收，回收没有正常关闭的http连接

			if (logger.IsEnabled(LogLevel.Debug))
			{
				logger.LogDebug("POST请求参数->url：{0}，paras：{1}，timeout：{2}", url, paras, timeout);
			}
			HttpWebRequest req = null;
			HttpWebResponse resp = null;
			try
			{
				//设置最大连接数
				ServicePointManager.DefaultConnectionLimit = 200;
				////设置https验证方式
				//if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
				//{
				//	ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
				//}

				req = (HttpWebRequest)WebRequest.Create(url);

				req.Method = "POST";
				req.Timeout = timeout * 1000;
				req.ContentType = "application/json; charset=utf-8";
				//设置代理服务器
				//WebProxy proxy = new WebProxy();                          //定义一个网关对象
				//proxy.Address = new Uri(WxPayConfig.PROXY_URL);              //网关服务器端口:端口
				//request.Proxy = proxy;


				if (paras != null)
				{
					byte[] bytesReq = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(paras));
					req.ContentLength = bytesReq.Length;//设置POST的数据长度
					using (Stream streamReq = req.GetRequestStream())//往服务器写入数据
					{
						streamReq.Write(bytesReq, 0, bytesReq.Length);
					}
				}

				//获取服务端返回
				resp = (HttpWebResponse)req.GetResponse();
				string respContentType = resp.ContentType;
				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("POST请求返回->类型：{0}，长度：{1}", respContentType, resp.ContentLength);
				}
				if (respContentType == "application/json; encoding=utf-8")
				{
					string result = string.Empty;//返回结果
												 //获取服务端返回数据
					using (Stream respStream = resp.GetResponseStream())
					{
						using (StreamReader sr = new StreamReader(respStream, Encoding.UTF8))
						{
							result = sr.ReadToEnd().Trim();
						}
					}
					return new HttpResult() { content = result, contentType = respContentType };
				}
				else if (resp.ContentLength > 0)
				{
					byte[] result = new byte[resp.ContentLength];
					byte[] buf = new byte[1024];
					using (Stream respStream = resp.GetResponseStream())
					{
						int reads = respStream.Read(buf, 0, buf.Length);
						int cur = 0;
						while (reads > 0)
						{
							Array.ConstrainedCopy(buf, 0, result, cur, reads);
							cur += reads;
							reads = respStream.Read(buf, 0, buf.Length);
						}
					}
					return new HttpResult() { buffer = result, contentType = respContentType };
				}
			}
			catch (System.Threading.ThreadAbortException e)
			{
				logger.LogError("POST请求出错，ThreadAbortException，" + e);
				System.Threading.Thread.ResetAbort();
			}
			catch (WebException e)
			{
				if (e.Status == WebExceptionStatus.ProtocolError)
				{
					logger.LogError("POST请求出错，WebException，StatusCode：" + ((HttpWebResponse)e.Response).StatusCode + "，StatusDescription：" + ((HttpWebResponse)e.Response).StatusDescription + "，" + e);
				}
				else
				{
					logger.LogError("POST请求出错，WebException，" + e);
				}
			}
			catch (Exception e)
			{
				logger.LogError("POST请求出错，Exception，" + e);
			}
			finally
			{
				//关闭连接和流
				if (resp != null)
				{
					resp.Close();
				}
				if (req != null)
				{
					req.Abort();
				}
			}
			return null;
		}

		public static string Get(string url, string paras, Encoding encoding, string ua)
		{
			//GC.Collect();
			if (logger.IsEnabled(LogLevel.Debug))
			{
				logger.LogDebug("GET请求参数->url：{0}，paras：{1}，encoding：{2}，ua：{3}", url, paras, encoding, ua);
			}
			HttpWebRequest req = null;
			WebResponse resp = null;
			string result = string.Empty;
			try
			{
				//ServicePointManager.DefaultConnectionLimit = 200;//设置最大连接数
				////设置https验证方式
				//if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
				//{
				//	ServicePointManager.ServerCertificateValidationCallback =
				//			new RemoteCertificateValidationCallback(CheckValidationResult);
				//}

				if (string.IsNullOrEmpty(paras))
				{
					req = (HttpWebRequest)WebRequest.Create(url);
				}
				else
				{
					if (url.IndexOf("?") >= 0)
					{
						req = (HttpWebRequest)WebRequest.Create(url + (url.EndsWith("&") || paras.StartsWith("&") ? "" : "&") + paras);
					}
					else
					{
						req = (HttpWebRequest)WebRequest.Create(url + (paras.StartsWith("?") ? "" : "?") + paras);
					}
				}
				if (!string.IsNullOrEmpty(ua))
				{
					req.UserAgent = ua;
				}
				req.Method = "GET";

				resp = req.GetResponse();
				using (Stream streamResp = resp.GetResponseStream())
				{
					using (StreamReader ser = new StreamReader(streamResp, encoding))
					{
						result = ser.ReadToEnd();
					}
				}
				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("GET请求返回->{0}", result);
				}
			}
			catch (System.Threading.ThreadAbortException e)
			{
				logger.LogError("GET请求出错，ThreadAbortException，" + e);
				System.Threading.Thread.ResetAbort();
			}
			catch (WebException e)
			{
				if (e.Status == WebExceptionStatus.ProtocolError)
				{
					logger.LogError("GET请求出错，WebException，StatusCode：" + ((HttpWebResponse)e.Response).StatusCode + "，StatusDescription：" + ((HttpWebResponse)e.Response).StatusDescription + "，" + e);
				}
				else
				{
					logger.LogError("GET请求出错，WebException，" + e);
				}
			}
			catch (Exception e)
			{
				logger.LogError("GET请求出错，Exception，" + e);
			}
			finally
			{
				//关闭连接和流
				if (resp != null)
				{
					resp.Close();
				}
				if (req != null)
				{
					req.Abort();
				}
			}
			return result;
		}

		public static string Get(string url)
		{
			return Get(url, null, Encoding.UTF8, string.Empty);
		}
	}
}
